home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
DDJ0992.ARJ
/
UNLOAD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-19
|
10KB
|
327 lines
////////////////////////////////////////////////////////////////////////////
//
// UNLOAD.C Copyright (c) 1992 by Mike Sax
//
// Unload is a small programmer's utility that lets you remove any program
// or DLL that is stuck in memory.
//
////////////////////////////////////////////////////////////////////////////
#define STRICT 1
#include <windows.h>
#include <string.h>
#include <toolhelp.h>
#include "unload.h"
// Global variables:
static HINSTANCE ghInstance;
// Exported functions:
BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
LONG lParam);
BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
LONG lParam);
BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam);
// Internal functions:
void static FillupComboBox(HANDLE hComboBox);
void static ShowItemInfo(HWND hDlg, HWND hComboBox);
void static KillTask(HTASK hTask, int nMethod);
BOOL static IsDLL(HMODULE hModule);
// The WinMain function is called at the beginning of our program
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
ghInstance = hInstance;
(void)lpCmdLine;
if (!hPrevInstance)
{
WNDCLASS wc;
// Register private dialog class
wc.style = 0l;
wc.lpfnWndProc = DefDlgProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = ghInstance;
wc.hIcon = LoadIcon(hInstance, "Unload");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Unload";
if (!RegisterClass(&wc))
return -1;
}
// Use a dialog box as our main window and pass the nCmdShow parameter
// in lParam of MainDlgProc's WM_INITDIALOG.
return DialogBoxParam(ghInstance, "Unload", NULL, (DLGPROC)
MakeProcInstance((FARPROC)MainDlgProc, ghInstance),
(LONG)nCmdShow);
// Proc Instance will be automatically cleaned up by Windows.
}
// MainDlgProc handles all messages for our main window.
BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
// We passed the nCmdShow parameter of WinMain in lParam
ShowWindow(hDlg, LOWORD(lParam));
break;
case WM_CLOSE:
EndDialog(hDlg, FALSE);
break;
case WM_COMMAND:
switch(wParam)
{
// Combo box notification message
case IDD_COMBOBOX:
if (HIWORD(lParam) == CBN_DROPDOWN)
FillupComboBox((HANDLE)LOWORD(lParam));
else if (HIWORD(lParam) == CBN_SELCHANGE)
{
static BOOL bFirst = TRUE;
if (bFirst)
{
SetDlgItemText(hDlg, IDD_MESSAGE, "Compuserve: 75470,1403");
bFirst = FALSE;
}
ShowItemInfo(hDlg, (HANDLE)LOWORD(lParam));
}
break;
// User pressed the "Unload" button
case IDD_UNLOAD:
{
FARPROC lpProc;
int nCurSel = (int)SendDlgItemMessage(hDlg, IDD_COMBOBOX,
CB_GETCURSEL, 0, 0l);
// If no item selected, do nothing
if (nCurSel == CB_ERR)
{
MessageBeep(0);
break;
}
lpProc = MakeProcInstance((FARPROC)WarningDlgProc,
ghInstance);
// Call "Unload" dialog box and pass the module handle
// in lParam of WarningDlgProc's WM_INITDIALOG
if (DialogBoxParam(ghInstance, "WARNING", hDlg,
(DLGPROC)lpProc, SendDlgItemMessage(hDlg,
IDD_COMBOBOX, CB_GETITEMDATA, nCurSel, 0l)))
{
// Give Windows a chance to process the WM_QUIT
// or WM_CLOSE messages we might have posted
Yield();
FillupComboBox(GetDlgItem(hDlg, IDD_COMBOBOX));
}
FreeProcInstance(lpProc);
}
}
break;
default:
return FALSE; // We did not process the message
}
return TRUE; // We processed the message
}
// FillupComboBox fills up the combo box with a list of all modules
// that are currently loaded. Every item in the list box also contains
// a "long" data item (attached using CB_SETITEMDATA) that is a combination
// of the module handle and the usage count.
void static FillupComboBox(HANDLE hComboBox)
{
int nIndex;
BOOL bSucces;
HMODULE hSelectedModule;
MODULEENTRY ModuleEntry;
// Keep the module handle of the item that is currently selected
nIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
hSelectedModule = (HMODULE) ((CB_ERR == nIndex) ? -1 :
HIWORD(SendMessage(hComboBox, CB_GETITEMDATA, nIndex, 0l)));
SendMessage(hComboBox, CB_RESETCONTENT, 0, 0l);
ModuleEntry.dwSize = sizeof (MODULEENTRY);
bSucces = ModuleFirst(&ModuleEntry);
while(bSucces)
{
if (IsDLL(ModuleEntry.hModule))
AnsiLower(ModuleEntry.szModule);
nIndex = (int)SendMessage(hComboBox, CB_ADDSTRING, 0,
(LONG) (LPSTR) ModuleEntry.szModule);
if ((nIndex != CB_ERR) && (nIndex != CB_ERRSPACE))
{
SendMessage(hComboBox, CB_SETITEMDATA, nIndex,
MAKELONG(ModuleEntry.wcUsage, ModuleEntry.hModule));
bSucces = ModuleNext(&ModuleEntry);
}
else
bSucces = FALSE;
}
// Check if the previously selected module is still in the list and
// if so, reselect it.
for (nIndex = SendMessage(hComboBox, CB_GETCOUNT, 0, 0l) - 1;
nIndex >= 0 ; --nIndex)
if ((HMODULE) HIWORD(SendMessage(hComboBox, CB_GETITEMDATA,
nIndex, 0)) == hSelectedModule)
{
SendMessage(hComboBox, CB_SETCURSEL, nIndex, 0l);
break;
}
ShowItemInfo(GetParent(hComboBox), hComboBox);
}
// Show information about the currently selected item in the combo box.
void static ShowItemInfo(HWND hDlg, HWND hComboBox)
{
int nCurSel;
nCurSel = (int)SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
if (CB_ERR == nCurSel)
{
SetDlgItemText(hDlg, IDD_FILENAME, "");
SetDlgItemText(hDlg, IDD_MODULE, "");
SetDlgItemText(hDlg, IDD_KIND, "");
SetDlgItemText(hDlg, IDD_USAGE, "");
EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), FALSE);
}
else
{
char szScrap[MAX_PATH + 1];
char *pcFilename;
DWORD dwData;
dwData = SendMessage(hComboBox, CB_GETITEMDATA, nCurSel, 0l);
GetModuleFileName((HMODULE)HIWORD(dwData), szScrap, MAX_PATH);
// Remove the path from the filename
pcFilename = strrchr(szScrap, '\\');
pcFilename = (pcFilename == NULL) ? szScrap : pcFilename + 1;
SetDlgItemText(hDlg, IDD_KIND, (IsDLL((HMODULE)HIWORD(dwData)) ?
"Library" : "Program"));
SetDlgItemText(hDlg, IDD_FILENAME, pcFilename);
SetDlgItemInt(hDlg, IDD_USAGE, LOWORD(dwData), FALSE);
wsprintf(szScrap, "%04x", HIWORD(dwData));
SetDlgItemText(hDlg, IDD_MODULE, (LPSTR) szScrap);
EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), LOWORD(dwData));
}
}
// When the user pressed the Unload button, the "warning dialog" appears
BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
LONG lParam)
{
static HMODULE hModule; // Only one dialog can be active!
switch(wMessage)
{
case WM_INITDIALOG:
// The handle of the module to be freed is in the hiword
// of lParam, passed on using DialogBoxParam. Since we
// use the same dialog box for both programs and libraries,
// we have to adjust our dialog a little, depending on the
// type of dialog.
if (IsDLL((HMODULE)HIWORD(lParam)))
{
EnableWindow(GetDlgItem(hDlg, IDD_TERMINATE), FALSE);
EnableWindow(GetDlgItem(hDlg, IDD_DESTROY), FALSE);
}
else
SetDlgItemText(hDlg, IDD_REFERENCEZERO,
"Post WM_QUIT message");
CheckDlgButton(hDlg, IDD_REFERENCEZERO, 1);
hModule = (HMODULE)HIWORD(lParam);
break;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
{
if (IsDLL(hModule))
{
int nUsage = GetModuleUsage(hModule);
while (nUsage--)
FreeLibrary(hModule);
}
else
{
BOOL bSucces;
TASKENTRY TaskEntry;
int nMethod =
(IsDlgButtonChecked(hDlg, IDD_REFERENCEZERO)) ? 0 :
(IsDlgButtonChecked(hDlg, IDD_TERMINATE)) ? 1 : 2;
TaskEntry.dwSize = sizeof(TASKENTRY);
bSucces = TaskFirst(&TaskEntry);
while(bSucces)
{
if (TaskEntry.hModule == hModule)
KillTask(TaskEntry.hTask, nMethod);
bSucces = TaskNext(&TaskEntry);
}
}
EndDialog(hDlg, TRUE);
}
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
}
break;
case WM_CLOSE:
EndDialog(hDlg, FALSE);
break;
default:
return FALSE;
}
return TRUE;
}
// KillTask kills a task using a method of your choice. It is called
// from the "Warning" dialog box when the user presses Ok.
void static KillTask(HTASK hTask, int nMethod)
{
switch(nMethod)
{
case 0: // Post WM_QUIT message
PostAppMessage(hTask, WM_QUIT, 0, 0l);
break;
case 1: // Terminate application
TerminateApp(hTask, NO_UAE_BOX);
break;
case 2: // Close all the task's windows
{
FARPROC lpProc = MakeProcInstance((FARPROC)EnumTaskWindowsFunc,
ghInstance);
EnumTaskWindows(hTask,(WNDENUMPROC)lpProc, 0l);
FreeProcInstance(lpProc);
}
break;
}
}
// EnumTaskWindowsFunc is called for every toplevel window that belongs to
// a task. It simply posts a WM_CLOSE message to this window.
BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam)
{
(void)lParam; // Avoid compiler warnings
if (GetParent(hWnd) == NULL)
PostMessage(hWnd, WM_CLOSE, 0, 0l);
return TRUE;
}
// IsDLL returns TRUE if the specified module is a Dynamic Link Library, or
// FALSE if it is a program.
BOOL static IsDLL(HMODULE hModule)
{
int i;
// The module handle is really the selector of a far pointer to
// the new-style .EXE header of the module. The bit at 0x8000 of
// the word at offset 0xC in this structure is set if it's a DLL.
MemoryRead((WORD)hModule, 0xCl, &i, sizeof(i));
return (i & 0x8000) ? TRUE : FALSE;
}